﻿#region COPYRIGHT© 2009-2012 Phillip Clark. All rights reserved.

// For licensing information see License.txt (MIT style licensing).

#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using FlitBit.Cache.CodeContracts;
using FlitBit.Core;
using FlitBit.Core.Parallel;

namespace FlitBit.Cache
{
	/// <summary>
	///   Interface for cache objects.
	/// </summary>
	/// <typeparam name="TKey">key type K</typeparam>
	/// <typeparam name="TValue">value type V</typeparam>
	[ContractClass(typeof(ContractForICache<,>))]
	public interface ICache<TKey, TValue> : IInterrogateDisposable
	{
		/// <summary>
		///   The Cache's name.
		/// </summary>
		string Name { get; }

		/// <summary>
		///   Flushes all items from the cache.
		/// </summary>
		void FlushAll();

		/// <summary>
		///   Asynchronously gets an item from the cache.
		/// </summary>
		/// <param name="key">the item's key</param>
		/// <param name="continuation">a continuation called upon completion</param>
		void Get(TKey key, Continuation<Tuple<TKey, TValue>> continuation);

		/// <summary>
		///   Asynchronously gets items from the cache.
		/// </summary>
		/// <param name="keys">keys of items to retrieve.</param>
		/// <param name="continuation">a continuation called upon completion</param>
		void Get(IEnumerable<TKey> keys, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation);

		/// <summary>
		///   Asynchronously puts an item in the cache.
		/// </summary>
		/// <param name="key">the item's key</param>
		/// <param name="item">the item.</param>
		/// <param name="continuation">an optioanl continuation called upon completion</param>
		void Put(TKey key, TValue item, Continuation<Tuple<TKey, TValue>> continuation);

		/// <summary>
		///   Asynchronously puts items in the cache.
		/// </summary>
		/// <param name="items">items to put into the cache.</param>
		/// <param name="continuation">an optional continuation called upon completion</param>
		void Put(IEnumerable<Tuple<TKey, TValue>> items, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation);

		/// <summary>
		///   Asynchronously removes an item from the cache. Only items actually present are returned to the
		///   continuation.
		/// </summary>
		/// <param name="key">the item's key</param>
		/// <param name="continuation">an optional continuation called upon completion</param>
		void Remove(TKey key, Continuation<Tuple<TKey, TValue>> continuation);

		/// <summary>
		///   Asynchronously removes items from the cache. Only items actually present are returned to the
		///   continuation.
		/// </summary>
		/// <param name="keys">keys of items to remove.</param>
		/// <param name="continuation">an optional continuation called upon completion</param>
		void Remove(IEnumerable<TKey> keys, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation);
	}

	namespace CodeContracts
	{
		/// <summary>
		///   CodeContracts Class for ICache&lt;,>
		/// </summary>
		[ContractClassFor(typeof(ICache<,>))]
		internal abstract class ContractForICache<TKey, TValue> : ICache<TKey, TValue>
		{
			#region ICache<K,V> Members

			public string Name { get { throw new NotImplementedException(); } }

			public void FlushAll()
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				throw new NotImplementedException();
			}

			public bool IsDisposed { get { throw new NotImplementedException(); } }

			public void Dispose()
			{
				throw new NotImplementedException();
			}

			public void Get(TKey key, Continuation<Tuple<TKey, TValue>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				Contract.Requires<ArgumentNullException>(continuation != null);

				throw new NotImplementedException();
			}

			public void Get(IEnumerable<TKey> keys, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				Contract.Requires<ArgumentNullException>(keys != null);
				Contract.Requires<ArgumentNullException>(continuation != null);

				throw new NotImplementedException();
			}

			public void Put(TKey key, TValue item, Continuation<Tuple<TKey, TValue>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				Contract.Requires<ArgumentNullException>(continuation != null);
				throw new NotImplementedException();
			}

			public void Put(IEnumerable<Tuple<TKey, TValue>> items, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				Contract.Requires<ArgumentNullException>(items != null);
				throw new NotImplementedException();
			}

			public void Remove(TKey key, Continuation<Tuple<TKey, TValue>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				throw new NotImplementedException();
			}

			public void Remove(IEnumerable<TKey> keys, Continuation<IEnumerable<Tuple<TKey, TValue>>> continuation)
			{
				Contract.Requires<ObjectDisposedException>(!IsDisposed);
				Contract.Requires<ArgumentNullException>(keys != null);
				throw new NotImplementedException();
			}

			#endregion
		}
	}
}